/**
 * 封装 layer 弹窗
 * @author rxliuli
 */
window.rxPrompt = new class RxPrompt {
    /**
     * 快速显示消息
     * 示例 {@code await msg('成功')}
     *
     * @param text 显示的消息内容
     * @param [type] 消息的类型，可选择 {@code 'success', 'danger', 'warning'}，默认为什么都没有
     * @return {Promise<any>} 弹窗关闭时的异步结果，如果你需要在弹窗关闭后再做某些操作（例如返回到上一页），这个返回值就很有用
     */
    msg(text, type) {
        const typeIconMap = new Map(
            Object.entries({
                success: 1,
                danger: 2,
                warning: 3,
            }),
        )

        return new Promise(resolve =>
            layer.msg(
                text,
                {
                    anim: 0,
                    icon: typeIconMap.get(type),
                },
                resolve,
            ),
        )
    }

    /**
     * 快速显示成功消息
     * 示例 {@code await successMsg('成功')}
     *
     * @param text 显示的消息内容
     * @return {Promise<any>} 弹窗关闭时的异步结果，如果你需要在弹窗关闭后再做某些操作（例如返回到上一页），这个返回值就很有用
     */
    successMsg(text) {
        return this.msg(text, 'success')
    }

    /**
     * 快速显示失败消息
     * 示例 {@code await dangerMsg('成功')}
     *
     * @param text 显示的消息内容
     * @return {Promise<any>} 弹窗关闭时的异步结果，如果你需要在弹窗关闭后再做某些操作（例如跳转到错误页面），这个返回值就很有用
     */
    dangerMsg(text) {
        return this.msg(text, 'danger')
    }

    /**
     * 快速显示警告消息
     * 示例 {@code await warningMsg('成功')}
     *
     * @param text 显示的消息内容
     * @return {Promise<any>} 弹窗关闭时的异步结果，如果你需要在弹窗关闭后再做某些操作（例如清空表单的错误值），这个返回值就很有用
     */
    warningMsg(text) {
        return this.msg(text, 'warning')
    }

    /**
     * 加载遮罩框
     *
     * @returns {Function} 一个关闭遮罩框的函数
     */
    load = ((num, lastId) => () => {
        lastId = layer.load(1)
        num++
        return () => {
            num--
            if (num < 0) {
                num = 0
            }
            if (num > 0) {
                return
            }
            layer.close(lastId)
        }
    })(0)

    /**
     * 提示某个表单元素的错误
     *
     * @param {String} text 提示内容
     * @param {String} id 选择器的 id/class，但最好使用 id
     * @param {Array} [tips] 显示的位置，分别是 1 上 2 右 3 下 4 左。默认显示在右侧
     * @param {Boolean} [tipsMore] 是否关闭其他的提示，默认不关闭
     * @returns {Number} 弹窗 id
     */
    tips(text, id, {tips = [2], tipsMore = true} = {}) {
        return layer.tips(text, id, {
            tips,
            tipsMore,
        })
    }

    /**
     * 弹出确认框
     * 这个确认框最多只有两个选项
     *
     * @param {String} text 确认文字内容
     * @param {Array<String>} btns 按钮文字数组
     * @returns {Promise} 异步的函数，{@code resolve} 绑定第一个按钮按下的回调，{@code reject} 绑定第二个按钮的文字
     */
    confirm(text, btns) {
        return new Promise((resolve) => {
            const id = layer.confirm(
                text,
                {
                    btn: btns,
                },
                () => {
                    layer.close(id)
                    resolve(true)
                },
                () => {
                    layer.close(id)
                    resolve(false)
                },
            )
        })
    }

    /**
     * 打开一个自定义页面弹窗
     *
     * @param {String} title 标题
     * @param {String} content 内容
     * @returns {Number} 弹窗 id
     */
    open(title, content) {
        return layer.open({
            type: 1,
            skin: 'layui-layer-rim', //加上边框
            area: ['80%', '80%'], //宽高
            title,
            content,
            maxmin: true,
        })
    }
}()